# -*- coding: utf-8 -*-

import json
import logging
from typing import Dict, Any, Optional

# 确保日志配置正确
if not logging.getLogger().handlers:
    logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 使用一个固定的logger名称，确保全局一致性
logger = logging.getLogger("neutral_response_generator")
logger.setLevel(logging.INFO)  # 显式设置级别

# 确保logger有handler
if not logger.handlers:
    # 添加一个stream handler，直接输出到控制台
    handler = logging.StreamHandler()
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    handler.setLevel(logging.INFO)
    logger.addHandler(handler)
    logger.propagate = True  # 允许传播到父logger


class NeutralResponseGenerator:
    """
    中性回答生成模块
    
    功能：在事实集合的基础上生成内容准确、无情绪倾向的中性回答
    """
    
    def __init__(self, model_handler=None, config=None):
        """
        初始化中性回答生成器
        
        Args:
            model_handler: 模型处理器
            config: 配置对象
        """
        self.model_handler = model_handler
        self.config = config
        
        # 口语化模板
        self.templates = {
            "症状描述": [
                "我有{症状}",
                "最近{症状}",
                "就是{症状}"
            ],
            "时间描述": [
                "大概{时间}了",
                "有{时间}了",
                "从{时间}开始"
            ],
            "程度描述": [
                "有点{程度}",
                "比较{程度}",
                "挺{程度}的"
            ],
            "伴随症状": [
                "还有{伴随症状}",
                "同时{伴随症状}",
                "另外{伴随症状}"
            ]
        }
    
    def generate_neutral_response(self, doctor_query: str, facts: Dict[str, Any]) -> str:
        """
        生成中性回答
        
        Args:
            doctor_query: 医生提问
            facts: 确认事实集合
            
        Returns:
            中性患者回答文本
        """
        try:
            # 1. 分析医生提问类型
            query_type = self._analyze_query_type(doctor_query)
            logger.info(f"医生提问类型: {query_type}")
            
            # 2. 从事实中提取关键信息
            key_info = self._extract_key_information(facts, query_type)
            logger.info(f"提取的关键信息: {key_info}")
            
            # 3. 生成中性回答
            if self.model_handler and hasattr(self.model_handler, '_call_model_generate'):
                # 使用LLM生成
                neutral_response = self._generate_with_llm(doctor_query, key_info, facts)
            else:
                # 使用模板生成
                neutral_response = self._generate_with_template(doctor_query, key_info, query_type)
            
            # 4. 后处理：确保回答简洁自然
            neutral_response = self._post_process_response(neutral_response)
            
            logger.info(f"生成中性回答: {neutral_response}")
            return neutral_response
            
        except Exception as e:
            logger.error(f"生成中性回答失败: {str(e)}")
            return "我有点不舒服，但说不太清楚。"
    
    def _analyze_query_type(self, doctor_query: str) -> str:
        """
        分析医生提问类型
        
        Args:
            doctor_query: 医生提问
            
        Returns:
            提问类型
        """
        query_lower = doctor_query.lower()
        
        # 症状询问
        if any(keyword in query_lower for keyword in ['症状', '不舒服', '疼', '痛', '难受']):
            return "症状询问"
        
        # 时间询问
        if any(keyword in query_lower for keyword in ['时间', '多久', '什么时候', '开始', '持续']):
            return "时间询问"
        
        # 程度询问
        if any(keyword in query_lower for keyword in ['程度', '严重', '厉害', '怎么样', '如何']):
            return "程度询问"
        
        # 伴随症状询问
        if any(keyword in query_lower for keyword in ['伴随', '还有', '其他', '一起', '同时']):
            return "伴随症状询问"
        
        # 一般询问
        return "一般询问"
    
    def _extract_key_information(self, facts: Dict[str, Any], query_type: str) -> Dict[str, Any]:
        """
        从事实中提取关键信息
        
        Args:
            facts: 事实集合
            query_type: 提问类型
            
        Returns:
            关键信息字典
        """
        key_info = {}
        
        try:
            # 提取症状信息
            if query_type in ["症状询问", "一般询问"]:
                symptom = self._extract_symptom_info(facts)
                if symptom:
                    key_info["症状"] = symptom
            
            # 提取时间信息
            if query_type in ["时间询问", "一般询问"]:
                time_info = self._extract_time_info(facts)
                if time_info:
                    key_info["时间"] = time_info
            
            # 提取程度信息
            if query_type in ["程度询问", "一般询问"]:
                severity = self._extract_severity_info(facts)
                if severity:
                    key_info["程度"] = severity
            
            # 提取伴随症状信息
            if query_type in ["伴随症状询问", "一般询问"]:
                accompanying = self._extract_accompanying_info(facts)
                if accompanying:
                    key_info["伴随症状"] = accompanying
            
            # 提取其他相关信息
            other_info = self._extract_other_info(facts)
            if other_info:
                key_info.update(other_info)
            
            return key_info
            
        except Exception as e:
            logger.warning(f"提取关键信息失败: {str(e)}")
            return {}
    
    def _extract_symptom_info(self, facts: Dict[str, Any]) -> Optional[str]:
        """提取症状信息"""
        # 从主诉中提取
        if "主诉" in facts and isinstance(facts["主诉"], dict):
            chief_complaint = facts["主诉"].get("value", "")
            if chief_complaint and chief_complaint not in ["未知", "无", "缺失"]:
                return chief_complaint
        
        # 从现病史中提取
        if "现病史" in facts and isinstance(facts["现病史"], dict):
            present_illness = facts["现病史"]
            if "症状" in present_illness and isinstance(present_illness["症状"], dict):
                symptom = present_illness["症状"].get("value", "")
                if symptom and symptom not in ["未知", "无", "缺失"]:
                    return symptom
        
        # 从主观表述中提取
        if "主观表述" in facts and isinstance(facts["主观表述"], dict):
            subjective = facts["主观表述"]
            if "疼痛部位" in subjective and isinstance(subjective["疼痛部位"], dict):
                location = subjective["疼痛部位"].get("value", "")
                if location and location not in ["未知", "无", "缺失"]:
                    return f"{location}不舒服"
        
        return None
    
    def _extract_time_info(self, facts: Dict[str, Any]) -> Optional[str]:
        """提取时间信息"""
        # 从现病史中提取
        if "现病史" in facts and isinstance(facts["现病史"], dict):
            present_illness = facts["现病史"]
            if "起病时间" in present_illness and isinstance(present_illness["起病时间"], dict):
                time_info = present_illness["起病时间"].get("value", "")
                if time_info and time_info not in ["未知", "无", "缺失"]:
                    return time_info
        
        return None
    
    def _extract_severity_info(self, facts: Dict[str, Any]) -> Optional[str]:
        """提取程度信息"""
        # 从现病史中提取
        if "现病史" in facts and isinstance(facts["现病史"], dict):
            present_illness = facts["现病史"]
            if "进展" in present_illness and isinstance(present_illness["进展"], dict):
                progress = present_illness["进展"].get("value", "")
                if progress and progress not in ["未知", "无", "缺失"]:
                    return progress
        
        # 从主观表述中提取
        if "主观表述" in facts and isinstance(facts["主观表述"], dict):
            subjective = facts["主观表述"]
            if "疼痛性质" in subjective and isinstance(subjective["疼痛性质"], dict):
                nature = subjective["疼痛性质"].get("value", "")
                if nature and nature not in ["未知", "无", "缺失"]:
                    return nature
        
        return None
    
    def _extract_accompanying_info(self, facts: Dict[str, Any]) -> Optional[str]:
        """提取伴随症状信息"""
        # 从现病史中提取
        if "现病史" in facts and isinstance(facts["现病史"], dict):
            present_illness = facts["现病史"]
            if "伴随症状" in present_illness and isinstance(present_illness["伴随症状"], dict):
                accompanying = present_illness["伴随症状"].get("value", "")
                if accompanying and accompanying not in ["未知", "无", "缺失", "null", "None"]:
                    return accompanying
        
        return None
    
    def _extract_other_info(self, facts: Dict[str, Any]) -> Dict[str, str]:
        """提取其他相关信息"""
        other_info = {}
        
        # 提取既往史
        if "既往史" in facts and isinstance(facts["既往史"], dict):
            past_history = facts["既往史"].get("value", "")
            if past_history and past_history not in ["未知", "无", "缺失"]:
                other_info["既往史"] = past_history
        
        # 提取药物过敏史
        if "药物过敏史" in facts and isinstance(facts["药物过敏史"], dict):
            allergy = facts["药物过敏史"].get("value", "")
            if allergy and allergy not in ["未知", "无", "缺失"]:
                other_info["药物过敏史"] = allergy
        
        return other_info
    
    def _generate_with_llm(self, doctor_query: str, key_info: Dict[str, Any], facts: Dict[str, Any]) -> str:
        """
        使用LLM生成中性回答
        
        Args:
            doctor_query: 医生提问
            key_info: 关键信息
            facts: 事实集合
            
        Returns:
            生成的中性回答
        """
        try:
            # 构建提示词
            prompt = self._build_llm_prompt(doctor_query, key_info, facts)
            
            # 使用统一 messages 结构调用，优先 Swift（如启用），否则走本地/API模型
            model_input = [
                {"role": "system", "content": "你是一位普通患者，请根据以下事实回答医生问题。不要加入情绪或主观推测，保持中性客观。"},
                {"role": "user", "content": prompt}
            ]
            logger.info(f"LLM输入: {model_input}")
            response = self.model_handler.generate_with_messages(model_input)
            logger.info(f"LLM输出: {response}")
            # 清理响应
            response = self._clean_llm_response(response)
            
            return response
            
        except Exception as e:
            logger.warning(f"LLM生成失败，回退到模板生成: {str(e)}")
            return self._generate_with_template(doctor_query, key_info, "一般询问")
    
    def _build_llm_prompt(self, doctor_query: str, key_info: Dict[str, Any], facts: Dict[str, Any]) -> str:
        """构建LLM提示词"""
        prompt = f"医生问题：{doctor_query}\n\n"
        prompt += "患者事实信息：\n"
        
        # 添加关键信息
        for key, value in key_info.items():
            prompt += f"- {key}：{value}\n"
        
        # 添加其他相关信息
        if "既往史" in facts and isinstance(facts["既往史"], dict):
            past_history = facts["既往史"].get("value", "")
            if past_history and past_history not in ["未知", "无", "缺失"]:
                prompt += f"- 既往史：{past_history}\n"
        
        if "药物过敏史" in facts and isinstance(facts["药物过敏史"], dict):
            allergy = facts["药物过敏史"].get("value", "")
            if allergy and allergy not in ["未知", "无", "缺失"]:
                prompt += f"- 药物过敏史：{allergy}\n"
        
        prompt += "\n请用日常口语回答医生的问题，保持简洁自然，不要添加任何前缀或标识。"#字数不要太多，
        
        return prompt
    
    def _clean_llm_response(self, response: str) -> str:
        """清理LLM响应"""
        # 移除可能的前缀
        prefixes_to_remove = ["患者：", "患者回答：", "回答：", "患者说："]
        for prefix in prefixes_to_remove:
            if response.startswith(prefix):
                response = response[len(prefix):].strip()
        
        # 移除多余的标点
        response = response.strip()
        if response.endswith("。"):
            response = response[:-1]
        
        return response
    
    def _generate_with_template(self, doctor_query: str, key_info: Dict[str, Any], query_type: str) -> str:
        """
        使用模板生成中性回答
        
        Args:
            doctor_query: 医生提问
            key_info: 关键信息
            query_type: 提问类型
            
        Returns:
            生成的中性回答
        """
        try:
            response_parts = []
            
            # 根据提问类型和关键信息生成回答
            if "症状" in key_info:
                symptom = key_info["症状"]
                if query_type == "症状询问":
                    response_parts.append(f"我有{symptom}")
                else:
                    response_parts.append(f"就是{symptom}")
            
            if "时间" in key_info:
                time_info = key_info["时间"]
                if query_type == "时间询问":
                    response_parts.append(f"大概{time_info}了")
                else:
                    response_parts.append(f"有{time_info}了")
            
            if "程度" in key_info:
                severity = key_info["程度"]
                if query_type == "程度询问":
                    response_parts.append(f"比较{severity}")
                else:
                    response_parts.append(f"有点{severity}")
            
            if "伴随症状" in key_info:
                accompanying = key_info["伴随症状"]
                response_parts.append(f"还有{accompanying}")
            
            # 如果没有提取到关键信息，使用默认回答
            if not response_parts:
                if query_type == "症状询问":
                    response_parts.append("我有点不舒服")
                elif query_type == "时间询问":
                    response_parts.append("有一段时间了")
                else:
                    response_parts.append("我说不太清楚")
            
            # 组合回答
            response = "，".join(response_parts)
            
            # 确保回答以句号结尾
            if not response.endswith("。"):
                response += "。"
            
            return response
            
        except Exception as e:
            logger.warning(f"模板生成失败: {str(e)}")
            return "我有点不舒服，但说不太清楚。"
    
    def _post_process_response(self, response: str) -> str:
        """
        后处理回答
        
        Args:
            response: 原始回答
            
        Returns:
            处理后的回答
        """
        try:
            # 移除多余的空格和标点
            response = response.strip()
            
            # 确保回答长度合理
            if len(response) > 200:
                response = response[:200] + "..."
            
            # 确保回答不为空
            if not response or response in ["", "。", "，"]:
                response = "我有点不舒服，但说不太清楚。"
            
            return response
            
        except Exception as e:
            logger.warning(f"后处理失败: {str(e)}")
            return "我有点不舒服，但说不太清楚。"
